#include <Arduino.h>
#include <Arduino_GFX_Library.h>
#include <lvgl.h>

#include "../include/touch.h"

#include "ui.h"
#include "ui_events.h"
#include "ui_helpers.h"

Arduino_DataBus *bus = new Arduino_SWSPI(GFX_NOT_DEFINED /* DC */, 38 /* CS */, 4 /* SCK */, 39 /* MOSI */, GFX_NOT_DEFINED /* MISO */);

Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
    9 /* DE */, 20 /* VSYNC */, 3 /* HSYNC */, 19 /* PCLK */,
    21 /* R0 */, 6 /* R1 */, 47 /* R2 */, 5 /* R3 */, 48 /* R4 */,
    12 /* G0 */, 16 /* G1 */, 13 /* G2 */, 15 /* G3 */, 14 /* G4 */, 7 /* G5 */,
    8 /* B0 */, 10 /* B1 */, 18 /* B2 */, 11 /* B3 */, 17 /* B4 */,
    1 /* hsync_polarity */, 10 /* hsync_front_porch */, 8 /* hsync_pulse_width */, 50 /* hsync_back_porch */,
    1 /* vsync_polarity */, 10 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 20 /* vsync_back_porch */);

Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
    480 /* width */, 854 /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
    bus, GFX_NOT_DEFINED /* RST */, ili9806e_type1_init_operations, sizeof(ili9806e_type1_init_operations));

static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf1;
static lv_color_t *disp_draw_buf2;
static lv_disp_drv_t disp_drv;

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
  lv_disp_flush_ready(disp);
}

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
  if (touch_has_signal())
  {
    if (touch_touched())
    {
      data->state = LV_INDEV_STATE_PR;

      /*Set the coordinates*/
      data->point.x = touch_last_x;
      data->point.y = touch_last_y;
    }
    else if (touch_released())
    {
      data->state = LV_INDEV_STATE_REL;
    }
  }
  else
  {
    data->state = LV_INDEV_STATE_REL;
  }
}

void setup(void)
{

  gfx->begin(10000000);
  gfx->fillScreen(BLACK);

  touch_init(gfx->width(), gfx->height(), gfx->getRotation());
  lv_init();

  screenWidth = gfx->width();
  screenHeight = gfx->height();

  disp_draw_buf1 = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenHeight * 65, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
  disp_draw_buf2 = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 65, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);

  lv_disp_draw_buf_init(&draw_buf, disp_draw_buf1, disp_draw_buf2, 480 * 65);

  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  disp_drv.user_data = NULL;
  lv_disp_drv_register(&disp_drv);

  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register(&indev_drv);

  ui_init();
}

void loop()
{
  lv_timer_handler();
  vTaskDelay(10);
}
